<template>
  <div>
    <antModel
      :GamebodyStyle="GamebodyStyle"
      :GameiconStyle="GameiconStyle"
      :gameName="gameName"
      :openGame="open"
      :GameheadStyle="GameheadStyle"
      @handleScreen="handleScreen"
    >
      <template #content>
        <div class="gameBody">
          <div class="gameBody_header">
            <a-button type="primary" class="gameBody_header_button one"
              ><span class="text-style1 gameBody_header_title">SCORE</span>
              <i class="text-style1 gameBody_header_score">{{ score }}</i>
            </a-button>
            <a-button type="primary" class="gameBody_header_button two">
              <span class="text-style1 gameBody_header_title">BEST</span>
              <i class="text-style1 gameBody_header_score">{{
                bestScore
              }}</i></a-button
            >
            <a-button
              type="primary"
              class="gameBody_header_button three"
              @click="reStart"
              >新开始</a-button
            >
          </div>
          <div class="gameBody_content">
            <ul class="gameBody_content-box">
              <!-- transition-group -->
              <!-- name="slide"
                tag="ul" -->
              <div class="gameBody_content-box-trans">
                <li
                  class="gameBody_content-box-item"
                  v-for="(num, index) in nums"
                  :key="index"
                  :id="'gameBody' + index"
                ></li>
              </div>
              <div
                v-for="(item, index) in activeItems"
                :key="item"
                :style="renderDivStyle[0] ? renderDivStyle[index] : ''"
                class="render_common"
              >
                {{
                  nums[index] === 0
                    ? ""
                    : renderDivStyle[index].width == "0rem"
                    ? ""
                    : nums[index]
                }}
              </div>
            </ul>
          </div>

          <p>键盘上下左右(或w,a,s,d)按键，开始游戏</p>
        </div>
      </template>
    </antModel>
  </div>
</template>
<script setup>
import antModel from "@/components/ant-component/ant-model/index.vue";
import {
  h,
  ref,
  reactive,
  defineProps,
  onMounted,
  onUnmounted,
  watch,
} from "vue";
import Index from "../index.vue";
import { resolveOnChange } from "ant-design-vue/es/vc-input/utils/commonUtils";
import { debounce } from "lodash";

const props = defineProps(["open"]);
const screenWidth = ref(0);
// 样式
const GamebodyStyle = {
  height: "41.25rem",
  backgroundColor: "#faf8ef",
};

const GameheadStyle = {
  backgroundColor: "#a18b75",
};
const GameiconStyle =
  "z-index:999; margin-left:30px; width: 1.5rem; height: 1.5rem;color: #34c759;";

// 游戏逻辑
const gameName = "2048";
const Gameopen = ref(true);
const start = { x: 0, y: 0 };

const nums = ref([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
const renderDivStyle = reactive({
  0: {},
  1: {},
  2: {},
  3: {},
  4: {},
  5: {},
  6: {},
  7: {},
  8: {},
  9: {},
  10: {},
  11: {},
  12: {},
  13: {},
  14: {},
  15: {},
});

const renderDiv = ref("");
const activeItems = ref([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
const score = ref(0);
const bestScore = ref(0);
const isMoving = ref(false);
watch(
  () => props.open,
  (val) => {
    window.addEventListener("keydown", handleKeyDown);
  }
);
onMounted(() => {
  // reStart();
  window.onresize = () => {
    handleScreen();
    return (() => {
      screenWidth.value =
        window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth;
    })();
  };
  // ocument.addEventListener("keyup", this.keyDown);
});
onUnmounted(() => {
  window.removeEventListener("keydown", handleKeyDown);
});

// 获取dom结构

// 动态渲染dom

const create = (item) => {
  const childElement = document.getElementById(`gameBody${item}`);
  const rect = childElement.getBoundingClientRect();
  const parentRect = childElement.parentElement.getBoundingClientRect();
  const grandparentRect =
    childElement.parentElement.parentElement.getBoundingClientRect();
  const offsetTopRelativeToGrandparent = rect.top - grandparentRect.top;
  const offsetLeftRelativeToGrandparent = rect.left - grandparentRect.left;
  return {
    width: pxToRem(rect.width),
    height: pxToRem(rect.height),
    left: pxToRem(offsetLeftRelativeToGrandparent),
    top: pxToRem(offsetTopRelativeToGrandparent),
  };
};
// px转换rem
const pxToRem = (px) => {
  let rootFontSize;

  if (480 < window.innerWidth && window.innerWidth <= 768) {
    rootFontSize = 14;
  } else if (window.innerWidth <= 480) {
    rootFontSize = 12;
  } else {
    rootFontSize = 16; // 默认值
  }
  // console.log(" window.innerWidth", window.innerWidth, rootFontSize);
  return px / rootFontSize;
};
// 动态渲染dom
const asyncRender = (info, content, index) => {
  // console.log("content", info, content, index);
  renderDivStyle[index].lineHeight = info.height + "rem";
  renderDivStyle[index].width = info.width + "rem";
  renderDivStyle[index].height = info.height + "rem";
  renderDivStyle[index].color = "#333";
  renderDivStyle[index].left = info.left + "rem";
  renderDivStyle[index].top = info.top + "rem";
  renderDivStyle[index].innerHTML = 1;
};
// 鼠标事件
const handleKeyDown = debounce((event) => {
  if (event.key === "w" || event.key === "ArrowUp") {
    // 处理向上事件
    console.log("向上");
    move(3);
  } else if (event.key === "s" || event.key === "ArrowDown") {
    // 处理向下事件
    console.log("向下");
    move(1);
  } else if (event.key === "a" || event.key === "ArrowLeft") {
    // 处理向左事件
    console.log("向左");
    move(0);
  } else if (event.key === "d" || event.key === "ArrowRight") {
    // 处理向右事件
    console.log("向右");
    move(2);
  }
}, 500);

// 新游戏
const reStart = () => {
  nums.value = Array(16).fill(0);
  for (let i = 0; i < 16; i++) {
    asyncRender({ width: 0, height: 0, left: 0, top: 0 }, 1, i);
  }

  score.value = 0;
  //随机添加2个
  let i = 0;
  while (i++ < 2) {
    randomAdd();
  }
  // randomAdd();
};
// 生成随机位置随机数字
const randomAdd = () => {
  let emptynums = [];
  nums.value.forEach((item, index) => {
    if (item === 0) {
      emptynums.push(index);
    }
  });
  if (emptynums.length === 0) {
    return;
  }
  let randomIndex = Math.floor(Math.random() * emptynums.length);
  // let randomNum = Math.random() > 0.5 ? 4 : 2;
  let randomNum = Math.random() > 0.5 ? 4 : 2;
  nums.value[emptynums[randomIndex]] = randomNum;
  let info = create(emptynums[randomIndex]);
  asyncRender(info, randomNum, emptynums[randomIndex]);
};

const findOriginalIndex = (arr, rotatedIndex, rotations) => {
  const l = arr.length;
  const d = Math.sqrt(l);

  // 逆向旋转次数
  let n = (4 - (rotations % 4)) % 4;
  // console.log("n", n);

  if (n === 0) return rotatedIndex; // 旋转 0 次时，索引不变

  // 将旋转后的索引转换为 (i, j) 坐标
  const originalI = rotatedIndex % d;
  const originalJ = Math.floor(rotatedIndex / d);

  // 逆向旋转 1 次
  if (n === 3) {
    return (d - 1 - originalI) * d + originalJ;
  }

  // 逆向旋转 2 次
  if (n === 2) {
    return (d - 1 - originalJ) * d + (d - 1 - originalI);
  }

  // 逆向旋转 3 次
  if (n === 1) {
    return originalI * d + (d - 1 - originalJ);
  }
};

// 向左移动滑块
const move = (i) => {
  let currentArr = [...T(nums.value, i)],
    hasMove = false,
    indexMap = {},
    hasCombin = {}; // 判断是否合并过
  currentArr.forEach((item, index) => {
    while (item !== 0 && index % 4) {
      // 不为0的处理
      if (currentArr[index - 1] === 0) {
        // 如果前一位置为0，则移动
        currentArr[index - 1] = item;
        currentArr[index] = 0;
        hasMove = true;
        if (hasCombin[index]) {
          hasCombin[index - 1] = true;
          hasCombin[index] = false;
        }
        let curkey = "";
        for (let key in indexMap) {
          if (indexMap.hasOwnProperty(key) && indexMap[key] === index) {
            curkey = key;
          }
        }
        if (curkey) {
          indexMap[curkey] = index - 1;
        } else {
          // console.log(456);

          indexMap[index] = index - 1;
        }

        // console.log("indexMap", indexMap);
      }
      // 如果前一位置数相同，则合并
      else if (item === currentArr[index - 1]) {
        currentArr[index - 1] = item * 2;
        score.value += currentArr[index - 1];
        if (score.value > bestScore.value) {
          bestScore.value = score.value;
        }
        currentArr[index] = 0;
        hasMove = true;
        hasCombin[index - 1] = true; //记录合并位置
        let curkey = "";
        for (let key in indexMap) {
          if (indexMap.hasOwnProperty(key) && indexMap[key] === index) {
            curkey = key;
          }
        }
        if (curkey) {
          indexMap[curkey] = index - 1;
        } else {
          // console.log(456);
          indexMap[index] = index - 1;
        }
      } else {
        break;
      }
      index--; // 更新 index
    }
  });

  for (let key in indexMap) {
    addTransitionClass(key, indexMap[key], i);
  }
  // clearTimeout(timer); // 清除定时器
  const timer = setTimeout(() => {
    nums.value = T(currentArr, 4 - i);
    hasMove && randomAdd();
    // console.log("新数组", nums.value);
  }, 500);
};
// 计算数组初始和结束位置
//arr 需要旋转的数组
//n  顺时针选择n次
const T = (arr, i) => {
  let n = i % 4;
  if (n === 0) return arr; // 修正条件，确保 n 为 0 时返回原数组
  const l = arr.length,
    d = Math.sqrt(l);
  let tmp = [];
  for (let i = 0; i < d; i += 1) {
    for (let j = 0; j < d; j += 1) {
      tmp[d - i - 1 + j * d] = arr[i * d + j];
    }
  }
  if (n > 1) tmp = T(tmp, n - 1); // 递归调用
  return tmp;
};
// 添加过渡类实现动画效果

const addTransitionClass = (
  fromIndex,
  toIndex,
  direction,
  isCombine = false
) => {
  // console.log(fromIndex, toIndex, direction, isCombine);
  let fromInfo = create(fromIndex);
  let toInfo = create(fromIndex);
  let endIndex = toIndex;
  let startIndex = fromIndex;
  switch (direction) {
    case 0:
      if (
        fromIndex !== 0 ||
        fromIndex !== 4 ||
        fromIndex !== 8 ||
        fromIndex !== 12
      ) {
        toInfo = create(Number(toIndex));
      }

      break;
    case 1:
      startIndex = findOriginalIndex(nums.value, fromIndex, 1);
      endIndex = Number(startIndex) + (Number(fromIndex) - Number(toIndex)) * 4;

      // if (fromIndex < 12) {
      //   toInfo = create(Number(fromIndex) + 4);
      // }
      break;
    case 2:
      startIndex = findOriginalIndex(nums.value, fromIndex, 2);
      endIndex = Number(startIndex) + Number(fromIndex) - Number(toIndex);
      // console.log("endIndex", endIndex, Number(fromIndex), Number(toIndex));
      // if (
      //   fromIndex !== 3 ||
      //   fromIndex !== 7 ||
      //   fromIndex !== 11 ||
      //   fromIndex !== 15
      // ) {
      //   toInfo = create(Number(endIndex));
      // }
      break;
    case 3:
      startIndex = findOriginalIndex(nums.value, fromIndex, 3);
      endIndex = Number(startIndex) - (Number(fromIndex) - Number(toIndex)) * 4;
      // console.log(
      //   "endIndex",
      //   endIndex,
      //   Number(fromIndex),
      //   Number(toIndex),
      //   startIndex
      // );
      // if (fromIndex > 3) {
      //   toInfo = create(Number(endIndex));
      // }
      break;
  }

  if (
    fromIndex !== 0 ||
    fromIndex !== 4 ||
    fromIndex !== 8 ||
    fromIndex !== 12
  ) {
    fromInfo = create(Number(startIndex));
    toInfo = create(Number(endIndex));
  }
  const parent = document.querySelector(".gameBody_content");
  const doms = parent.querySelectorAll(".render_common");
  let info = {
    left: toInfo.left - fromInfo.left,
    top: toInfo.top - fromInfo.top,
  };
  // 移动动画
  moveRender(direction, doms[startIndex], info, isCombine);
  let endInfo = create(Number(endIndex));
  // console.log("endInfo", endInfo);

  setTimeout(() => {
    asyncRender({ width: 0, height: 0, left: 0, top: 0 }, 1, startIndex);
    doms[startIndex].style.transform = `translate(0, 0)`;
    doms[startIndex].style.transition = `transform 0ms ease-in-out`;
    asyncRender(endInfo, 1, endIndex);
  }, 500);
};

// 移动动画
const moveRender = (direction, dom, info, isCombine) => {
  const moveDuration = 500; // 合并时动画时间稍长
  dom.style.transition = `transform ${moveDuration}ms ease-in-out`;
  dom.addEventListener("transitionend", () => {
    // console.log("过渡结束", event);
  });
  switch (direction) {
    case 0: // 左
      dom.style.transform = `translate(${info.left}rem, 0)`;
      break;
    case 1: // 下
      dom.style.transform = `translate(0, ${info.top}rem)`;
      break;
    case 2: // 右
      dom.style.transform = `translate(${info.left}rem, 0)`;
      break;
    case 3: // 上
      dom.style.transform = `translate(0, ${info.top}rem)`;
      break;
    default:
      console.error("Invalid direction:", direction);
      break;
  }
  isMoving.value = false; // 移动动画结束后，将isMoving设置为false
};

// 放大缩小响应式
const handleScreen = (flag) => {
  // console.log(213, nums.value);

  nums.value.forEach((item, index) => {
    if (item > 0) {
      // console.log(222);
      let info = create(index);
      asyncRender(info, 1, index);
    }
  });
};
</script>
<style lang="scss" scoped>
.gameBody {
  width: 50%;
  height: 100%;
  // width: 34.625rem;
  // height: 36.25rem;
  box-sizing: border-box;
  padding: 10px 0;
  .gameBody_header {
    display: flex;
    position: relative;
    .gameBody_header_button {
      display: flex;
      width: 6.25rem;
      height: 4.25rem;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      background-color: #bbada0;
      border: 1px solid #bbada0;
      color: #fff;
      font-size: 1.25rem;
      font-weight: 700;
      box-shadow: none;
      margin-right: 0.625rem;
      .gameBody_header_title {
        font-size: 1.125rem;
        font-weight: 700;
        color: #eee4da;
      }
    }
    .gameBody_header_button:last-child {
      position: absolute;
      right: 0%;
      margin-right: 0;
    }
    .three {
      width: 7.5rem;
      background-color: #8f7a66;
      border: 1px solid #8f7a66;
    }
  }
  .gameBody_content {
    width: 100%;
    height: 85%;
    margin-top: 0.3125rem;
    background-color: #bbada0;
    overflow: hidden;
    .gameBody_content-box-trans {
      display: inline-grid;
      grid-template-columns: repeat(4, 25%);
      grid-template-rows: repeat(4, 25%);
      // white-space: nowrap;
      justify-content: center;
      justify-items: center;
      align-items: center;
      // gap: .75rem; /* 间距 */
      width: 100%;
      height: 100%;
      overflow: hidden;
    }
    .gameBody_content-box {
      position: relative;
      // display: flex;
      // flex-wrap: wrap;
      width: 100%;
      height: 100%;
      // justify-content: space-between;
      // padding: 4% 3% 0% 3%;
      overflow: hidden;
      z-index: 9999;
      .gameBody_content-box-item {
        display: flex;
        width: 92%;
        height: 92%;
        // width: 6.875rem;
        // height:  6.875rem;

        border-radius: 0.3125rem;
        background-color: #cdc1b4;
        font-size: 2.1875rem;
        font-weight: 700;
        color: #fff;
        transition: all 3s;
      }
      .gameBody_content-box-item:nth-child(4n) {
        margin-right: 0;
      }
      .gameBody_content_cur {
        position: absolute;

        width: 22%;
        height: 21%;
        border-radius: 0.3125rem;
        font-size: 2.1875rem;
        font-weight: 700;
        // display: flex;
        // flex-wrap: wrap;
        background-color: #eee4da;
        // transform: translate(8.5rem, 8.125rem);
      }
    }
  }
}

.render_common {
  text-align: center;
  position: absolute;
  color: "#333";
  font-size: 2.1875rem;
  font-weight: 700;
  border-radius: 0.3125rem;
  background-color: #eee4da;
  // transition: transform 3s;
  transform: translate(0, 0);
}
// .render_common:hover {
//   // transform: translate(0, 100%);
// }
@media (max-width: 768px) {
  .gameBody {
    width: 100%;
    left: 0;
    top: 0;
    position: relative; /* 确保布局不会溢出 */
  }
}
</style>
